﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using System;
using System.Text;
using Newtonsoft.Json;

public class UDPModule : MonoBehaviour
{
    [SerializeField]
    private int _port = 33200;

    private UdpClient _udpClient = null;
    JsonSerializerSettings settings;

    // Start is called before the first frame update
    IEnumerator Start()
    {
        settings = new JsonSerializerSettings();
        settings.Formatting = Formatting.Indented;
        yield return new WaitForEndOfFrame();
        var cfgLoader = GameObject.FindObjectOfType<ConfigLoader>();
        if (cfgLoader!=null)
        {
            _port = cfgLoader.UDPPort;
            Debug.Log($"使用配置文件中的UDP端口:{_port}");
        }
        _udpClient = new UdpClient(_port);
        _udpClient.BeginReceive(OnRec, null);
        // get local ip
        var host = Dns.GetHostEntry(Dns.GetHostName());
        foreach (IPAddress ipAddress in host.AddressList)
        {
            // 过滤掉IPv6地址和非本地链接地址
            if (ipAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork && !IPAddress.IsLoopback(ipAddress))
            {
                SendIP = ipAddress.ToString();
                Debug.Log("本机IP地址: " + ipAddress.ToString());
                break;
            }
        }
    }

    void OnDestroy()
    {
        if (_udpClient != null)
            _udpClient.Close();
    }

    public string SendIP = null;
    public int SendPort = 25544;

    public bool DevReqLog = true;
    public bool DevRspLog = true;

    public bool DevRspFmt = true;

    public void Send(string s)
    {
        IPEndPoint ipep;
        if (IPAddress.TryParse(SendIP, out IPAddress ip))
            ipep = new IPEndPoint(ip, SendPort);
        else
            ipep = new IPEndPoint(IPAddress.Loopback, SendPort);

        var sendData = Encoding.UTF8.GetBytes(s);
        _udpClient.Send(sendData, sendData.Length, ipep);
        Debug.Log("UDP发送:" + s);
    }

    void OnRec(IAsyncResult ar)
    {
        if (!this)
            return;

        IPEndPoint ipep = new IPEndPoint(IPAddress.Any, _port);
        byte[] data = _udpClient.EndReceive(ar, ref ipep);
        Rsp(data, ipep);
        _udpClient.BeginReceive(OnRec, _udpClient);
    }

    void Rsp(byte[] data, IPEndPoint remote)
    {
        try
        {
            var str = Encoding.UTF8.GetString(data);
            var list = JsonConvert.DeserializeObject<List<DeviceStatusReq>>(str);
            if(DevReqLog)
                Debug.Log("UDP收到:" + str);

            var rspList = new List<DeviceStatus>();
            foreach (var req in list)
            {
                var dev = DeviceManager.Instance.GetDevice(req.DevType, req.DevId);
                if (dev == null)
                    continue;

                dev.HandleCmd(req.DevCmd, req.DevArg);
                rspList.Add(dev.GetDeviceStatus());
            }
            // send
            var sendJsonStr = JsonConvert.SerializeObject(rspList, DevRspFmt ? settings : null);
            var sendData = Encoding.UTF8.GetBytes(sendJsonStr);
            _udpClient.Send(sendData, sendData.Length, remote);
            if (DevRspLog)
                Debug.Log("UDP回复:" + sendJsonStr);
        }
        catch (Exception e)
        {
            Debug.LogError("尝试回应时产生错误:");
            Debug.LogException(e);

            // send
            var sendJsonStr = e.Message.ToString();
            var sendData = Encoding.UTF8.GetBytes(sendJsonStr);
            _udpClient.Send(sendData, sendData.Length, remote);
        }
    }
}
